using System.Linq;
using CardPlay.Model.CardModel;
using CardPlay.Model.GameModel;
using CardPlay.Model.GameModel.Actions;
using CardPlay.Model.GameModel.Presentation;
using CardPlay.Model.Layout;
using CardPlay.Model.Primitives;

namespace CardPlay.DemoPack.Games.SlyFoxVariants
{
    public abstract class TwentyBase : StandardCardGame
    {
        public const string FamilyName = "Sly Fox";

        protected TwentyBase()
        {
            NamesOfAdditionalPiles.AddRange(new[]{ Stock, Waste });
            CardsPerDeal = 20;

            TotalDecks = 2;
            TotalFoundations = 8;

            TableauColumns = 5;
            TableauRows = 4;
        }

        public override ILayoutSite CreatePresentation(IPresentationContext presentation)
        {
            var root = presentation.CreateRowLayout();

            var stockWasteColumn = presentation.CreateColumnLayout();
            root.Add(stockWasteColumn);
            root.Add(presentation.CreateMimimalSpacer());

            PrepareStockPresentation(presentation, stockWasteColumn);

            var tableau = new UniformGridLayout { Columns = TableauColumns, Rows = TableauRows };
            root.Add(tableau);
            root.Add(presentation.CreateMimimalSpacer());

            PrepareTableauPresentation(presentation, tableau);

            var foundationRanks = new[] { Rank.Ace, Rank.King };

            for (var i = 0; i < foundationRanks.Length; ++i)
            {
                root.Add(presentation.CreateMimimalSpacer());

                var foundations = presentation.CreateColumnLayout();
                root.Add(foundations);

                presentation.AddPiles(foundations,
                    NamesOfFoundations.Skip(i * CardFace.SuitsPerDeck).Take(CardFace.SuitsPerDeck),
                    presentation.StyleForRepeatedRankFoundation(this, foundationRanks[i], 1));
            }

            return root;
        }

        protected abstract void PrepareStockPresentation(IPresentationContext presentation, SideBySideLayout stockWasteColumn);

        protected virtual void PrepareTableauPresentation(IPresentationContext presentation, CompositeLayout tableau)
        {
            var metrics = presentation.Metrics;

            var tableauStyle = new VisualTraits
            {
                Arrangement = CardArrangement.StackSquare,
                EmptyCue = () => EmptyPileCue.CardSite,
                ContentFit = ContentFit.FitBounds,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Top,
                MinimumSize = metrics.CardSize + new Size(metrics.MinSpacingAcross, metrics.MaxSpacingDown)
            };

            presentation.AddPiles(tableau, NamesOfTableaus, tableauStyle);
        }

        protected override bool AllowedToBuildFoundation(MovePileAction action)
        {
            return action.IsBuildingTwoDeckFoundation();
        }

        protected int TableauColumns { get; set; }

        protected int TableauRows
        {
            get { return TotalTableaus / TableauColumns; }
            set { TotalTableaus = value * TableauColumns; }
        }

        protected string TableauNameAt(int col, int row)
        {
            return StandardPileNames.PrefixForTableau + (row * TableauColumns + col + 1);
        }

        protected Point PointFromTableauLocation(PartLocation location)
        {
            var index = location.GetOrdinal() - 1;
            return new Point(index % TableauColumns, index / TableauColumns);
        }
    }
}